#include "Pajarito.h"
#include "ActoresConstantes.h"
#include "UtilidadesConstantes.h"

using namespace TP::Juego::Arena::Actores;

Pajarito::Pajarito(): Actor("", new Rol (PAJARITO, PAJARITO)){
}

Pajarito::Pajarito(const string& pNombre): Actor(pNombre, new Rol (pNombre, PAJARITO)) {
}

Pajarito::~Pajarito() {}

IColisionado* Pajarito::colisionar (IColisionado* pColisionado){
    
    // Se verifica que haya algo para colisionar.
    //if (!pColisionado) return pColisionado;
    
    // El pajarito no se puede colisionar con sigo mismo.
    //if (this == pColisionado) return pColisionado;
    
    // Ver si se colisiona contra piso o perímetro o contra otra cosa
    if(pColisionado->getRol()->Descripcion() == DESC_PERIMETRO ||
            pColisionado->getRol()->Descripcion() == DESC_PISO) {
        // Colision cilindro-recta
        if (pColisionado->getRol()->Descripcion() == DESC_PERIMETRO) {
            return (IColisionado*) this->colisionarContraPerimetro ((Perimetro*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_PISO) {
            return (IColisionado*) this->colisionarContraPiso ((Piso*)pColisionado);
        }
    }
    else {
        // Colisión de cilindros
//        if(pColisionado) {
//            
//        }
        if (pColisionado->getRol()->Descripcion() == DESC_CERDITO) {
            return (IColisionado*) this->colisionarContraCerdito ((Cerdito*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_MONTICULOHUEVOS) {
            return (IColisionado*) this->colisionarContraMonticuloHuevo ((MonticuloHuevos*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_FRUTA) {
            return (IColisionado*) this->colisionarContraFruta ((Fruta*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_CAJA) {
            return (IColisionado*) this->colisionarContraCaja ((Caja*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == HUEVO) {
            return (IColisionado*) this->colisionarContraHuevo ((Huevo*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == PAJARITO) {
            return (IColisionado*) this->colisionarContraPajarito ((Pajarito*)pColisionado);
        }   
    }
}

Perimetro* Pajarito::colisionarContraPerimetro (Perimetro* pPerimetro) {
    if((this->getTrayectoria()->getPosicion()->X() - this->getRadio() < 0) ||
            (this->getTrayectoria()->getPosicion()->X() + this->getRadio() > pPerimetro->getAncho()) ||
            (this->getTrayectoria()->getPosicion()->Y() - this->getRadio() < 0) ||
            (this->getTrayectoria()->getPosicion()->Y() + this->getRadio() > pPerimetro->getAlto()) )
        this->destruir();
    return pPerimetro;
}

Piso* Pajarito::colisionarContraPiso (Piso* pPiso) {
    // TODO: hacer choque contra el piso.    
    //this->destruir();
    return pPiso;
}

Cerdito* Pajarito::colisionarContraCerdito(Cerdito* pCerdito) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pCerdito->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pCerdito->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pCerdito->decrementarEnergia(this->getPoderAtaqueContraCerdito());
    }
    return pCerdito;
}

Huevo* Pajarito::colisionarContraHuevo(Huevo* pHuevo) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pHuevo->getTrayectoria()->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pHuevo->getTrayectoria()->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();

    if(dr < sumRadio)
        this->decrementarEnergia(pHuevo->getPoderAtaqueContraPajarito());
    return pHuevo;
}

MonticuloHuevos* Pajarito::colisionarContraMonticuloHuevo(MonticuloHuevos* pMonticuloHuevos) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pMonticuloHuevos->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pMonticuloHuevos->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pMonticuloHuevos->decrementarEnergia(this->getPoderAtaqueContraSuperficie());
    }
    return pMonticuloHuevos;
}

Caja* Pajarito::colisionarContraCaja(Caja* pCaja) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pCaja->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pCaja->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        pCaja->decrementarEnergia(this->getPoderAtaqueContraSuperficie());
        this->destruir();
    }        
    return pCaja;
}

Fruta* Pajarito::colisionarContraFruta(Fruta* pFruta) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pFruta->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pFruta->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pFruta->destruir();
    }
    return pFruta;
}

Pajarito* Pajarito::colisionarContraPajarito(Pajarito* pPajarito) {
    return pPajarito;
}


string Pajarito::aXML(){

    TiXmlDocument* doc = new TiXmlDocument();
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());

    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

string Pajarito::aXML(const string& pPath){

    TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());
    
    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

void Pajarito::parseXML (const string& pDescriptor){

    TiXmlDocument doc;
    doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
    this->deElementoXML(doc.FirstChildElement());
}

double Pajarito::getAlturaRebote() {
    return _alturaRebote;
}
    
void Pajarito::setAlturaRebote(double alturaRebote) {
    _alturaRebote = alturaRebote;
}
    